<?php
namespace common\utils;

use Da\QrCode\QrCode;
use yii\base\Exception;
use Yii;

/**
 */
class ImageUtil {
    /**
     * @param string $imgSrc
     * @param string $imgDist
     *
     * @return string
     * @throws Exception
     */
    public static function mergePromotePng($imgSrc = '', $imgDist = '', $dstX = 0, $dstY = 0, $srcX = 0, $srcY = 0) {
        //图片二
        $imgSrc =  Yii::getAlias('@uploads') . $imgSrc;
        //图片一
        $imgDist = Yii::getAlias('@uploads') . $imgDist;
        //创建图片对象
        //imagecreatefrompng($filename)--由文件或 URL 创建一个新图象
        $image_1 = imagecreatefrompng($imgDist);
        $image_2 = imagecreatefrompng($imgSrc);
        //合成图片
        //imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )---拷贝并合并图像的一部分
        //将 src_im 图像中坐标从 src_x，src_y 开始，宽度为 src_w，高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度，其值范围从 0 到 100。当 pct = 0 时，实际上什么也没做，当为 100 时对于调色板图像本函数和 imagecopy() 完全一样，它对真彩色图像实现了 alpha 透明。
        $resultImg = imagecopymerge($image_1, $image_2, $dstX, $dstY, $srcX, $srcY, imagesx($image_2), imagesy($image_2), 100);
//        $resultImg = imagecopyresampled($image_1, $image_2, $dstX, $dstY, $srcX, $srcY, imagesx($image_2), imagesy($image_2), 100);
        //        $resultImg = imagecopymerge($image_1, $image_2, 270, 880, 0, 0, 215, 215, 100);
        if ($resultImg === false) {
            throw new Exception('图片合成失败');
        }

        //获取名称
        $filePath = Yii::getAlias('@uploads').'/poster/';
        if (!file_exists($filePath)) {
            mkdir($filePath);
            chmod($filePath, 0777);
        }
        $fileName = '/poster/' . time() . Yii::$app->user->getId(). rand(100,999). '.png';

        if (imagepng($image_1, Yii::getAlias('@uploads') . $fileName) === false) {
            throw new Exception('海报存储失败');
        }
        return $fileName;
    }

    /**
     * 创建推广链接
     * @param string $info
     * @param int $size
     * @param int $margin
     * @param int $R
     * @param int $G
     * @param int $B
     * @return string
     */
//    public static function createLink($info = '', $size = 315, $margin = 5, $R = 51, $G = 153, $B = 255){
    public static function createLink($info = '', $size = 315, $margin = 5, $R = 0, $G = 0, $B = 0){
        $qrCode = (new QrCode($info))
            ->setSize($size)
            ->setMargin($margin)
            ->useForegroundColor($R, $G, $B);
        $result = $qrCode->writeString();
        return $result;
    }


    /**
     *  二维码加入logo
     * @param string $imgSrc 图片2
     * @param string $imgDist 图片1
     * @param int $dstX
     * @param int $dstY
     * @param int $srcX
     * @param int $srcY
     * @return string
     * @throws Exception
     */
    public function mergeFaceAndQrCode($imgSrc = '', $imgDist = '', $dstX = 0, $dstY = 0, $srcX = 0, $srcY = 0) {
        //创建图片对象
        //imagecreatefrompng($filename)--由文件或 URL 创建一个新图象
        //imagecreatefromjpeg($filename)--由文件或 URL 创建一个新图象
        //imagecreatefromgif($filename)--由文件或 URL 创建一个新图象
        //imagecreatefromstring($filename)--由文件或 URL 创建一个新图象
        //原始图片
        $imageQR = imagecreatefromstring(file_get_contents($imgSrc));
//        list($withDist, $heightDist) = getimagesize($imgSrc);

        // 放置小图片
        $imageLogo = imagecreatefromstring(file_get_contents($imgDist));
        list($withSrc, $heightSrc) = getimagesize($imgSrc);


        $QRWidth = imagesx($imageQR);
        $QRHeight = imagesy($imageQR);

        $logoWidth = imagesx($imageLogo);
        $logoHeight = imagesy($imageLogo);

        $logoQrWidth = $QRWidth / 6;
        $scale = $logoWidth / $logoQrWidth;
//        $logoQrHeight = $logoHeight / $scale;
        $logoQrHeight = $QRHeight / 6;
        $fromWidth = ($QRWidth - $logoQrWidth) / 2;

        // 生成小的logo图片
        $handleLogoImg = imagecreatetruecolor($logoQrWidth, $logoQrHeight);
        imagecopyresampled($handleLogoImg, $imageLogo, 0, 0, 0, 0, $logoQrWidth, $logoQrHeight, $logoWidth, $logoHeight);
        // 描边
        list($handleLogoImg, $handleLogoWidth, $handleLogoHeight) = $this->imageOutline($handleLogoImg);

        // 圆角处理
        $handleLogoImg = $this->imageFillet($handleLogoImg);


        //合成图片
        //imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )---拷贝并合并图像的一部分
        //将 src_im 图像中坐标从 src_x，src_y 开始，宽度为 src_w，高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度，其值范围从 0 到 100。当 pct = 0 时，实际上什么也没做，当为 100 时对于调色板图像本函数和 imagecopy() 完全一样，它对真彩色图像实现了 alpha 透明。

        $posX = ($QRWidth - $handleLogoWidth) / 2;
        $posY = ($QRHeight - $handleLogoHeight) / 2;
        $destImg = $this->imagecopymergeAlpha($imageQR, $handleLogoImg, $posX, $posY, 0, 0, $handleLogoWidth, $handleLogoHeight, 100);

        ob_start();   //启用输出缓冲
        imagepng($destImg);    //输出图像
        $destImgContent = ob_get_contents();    //将缓冲的数据存入变量
        ob_end_clean();    //结束并清空输出缓存
        return $destImgContent;

    }


    // 合拼图片并保留各自透明度
    private function imagecopymergeAlpha($dest_img, $src_img, $pos_x, $pos_y, $src_x, $src_y, $src_w, $src_h, $opacity){
        $w = imagesx($src_img);
        $h = imagesy($src_img);
        $tmp_img = imagecreatetruecolor($src_w, $src_h);
        imagecopy($tmp_img, $dest_img, 0, 0, $pos_x, $pos_y, $src_w, $src_h);
        imagecopy($tmp_img, $src_img, 0, 0, $src_x, $src_y, $src_w, $src_h);
        imagecopymerge($dest_img, $tmp_img, $pos_x, $pos_y, $src_x, $src_y, $src_w, $src_h, $opacity);
        return $dest_img;
    }

    /**
     * 对图片对象进行描边
     * @param Obj  $img 图片对象
     * @return Array
     */
    private function imageOutline($img, $outLineSize = 0){
        ini_set('memory_limit', '2048M');
        // 获取图片宽高
        $img_w = imagesx($img);
        $img_h = imagesy($img);
        // 计算描边尺寸，没有设定则按比例自动计算
        $bg_w = $outLineSize ? intval($img_w + $outLineSize) : $img_w + (int)($img_w/5);
        $bg_h = $outLineSize ? intval($img_h + $outLineSize) : $img_h + (int)($img_h/5);
        // 创建底图对象
        $bg_img = imagecreatetruecolor($bg_w, $bg_h);
        // 设置底图颜色
        $rgb = $this->hex2rgb("#FFFFFF");
        $bgcolor = imagecolorallocate($bg_img, $rgb['r'], $rgb['g'], $rgb['b']);
        // 填充底图颜色
        imagefill($bg_img, 0, 0, $bgcolor);
        // 合拼图片与底图，实现描边效果
        imagecopy($bg_img, $img, (int)(($bg_w-$img_w)/2), (int)(($bg_h-$img_h)/2), 0, 0, $img_w, $img_h);
        $img = $bg_img;
        return [
            $img,
            $bg_w,
            $bg_h
        ];
    }

    /**
     * 对图片对象进行圆角处理
     * @param Obj $img 图片对象
     * @return Obj
     */
    private function imageFillet($img){
        // 获取图片宽高
        $img_w = imagesx($img);
        $img_h = imagesy($img);
        // 创建圆角图片对象
        $new_img = imagecreatetruecolor($img_w, $img_h);
        // 保存透明通道
//        imagesavealpha($new_img, true);
        // 填充圆角图片
        $bg = imagecolorallocatealpha($new_img, 255, 255, 255, 127);
        imagefill($new_img, 0, 0, $bg);
        // 圆角半径
        $r = 10;
        // 执行圆角处理
        for($x=0; $x<$img_w; $x++){
            for($y=0; $y<$img_h; $y++){
                $rgb = imagecolorat($img, $x, $y);
                // 不在图片四角范围，直接画图
                if(($x>=$r && $x<=($img_w-$r)) || ($y>=$r && $y<=($img_h-$r))){
                    imagesetpixel($new_img, $x, $y, $rgb);
                    // 在图片四角范围，选择画图
                }else{
                    // 上左
                    $ox = $r; // 圆心x坐标
                    $oy = $r; // 圆心y坐标
                    if( ( ($x-$ox)*($x-$ox) + ($y-$oy)*($y-$oy) ) <= ($r*$r) ){
                        imagesetpixel($new_img, $x, $y, $rgb);
                    }
                    // 上右
                    $ox = $img_w-$r; // 圆心x坐标
                    $oy = $r;    // 圆心y坐标
                    if( ( ($x-$ox)*($x-$ox) + ($y-$oy)*($y-$oy) ) <= ($r*$r) ){
                        imagesetpixel($new_img, $x, $y, $rgb);
                    }
                    // 下左
                    $ox = $r;    // 圆心x坐标
                    $oy = $img_h-$r; // 圆心y坐标
                    if( ( ($x-$ox)*($x-$ox) + ($y-$oy)*($y-$oy) ) <= ($r*$r) ){
                        imagesetpixel($new_img, $x, $y, $rgb);
                    }
                    // 下右
                    $ox = $img_w-$r; // 圆心x坐标
                    $oy = $img_h-$r; // 圆心y坐标
                    if( ( ($x-$ox)*($x-$ox) + ($y-$oy)*($y-$oy) ) <= ($r*$r) ){
                        imagesetpixel($new_img, $x, $y, $rgb);
                    }
                }
            }
        }
        return $new_img;
    }

    /** hex颜色转rgb颜色
     * @param String $color hex颜色
     * @return Array
     */
    private function hex2rgb($hexcolor){
        $color = str_replace('#', '', $hexcolor);
        if (strlen($color) > 3) {
            $rgb = array(
                'r' => hexdec(substr($color, 0, 2)),
                'g' => hexdec(substr($color, 2, 2)),
                'b' => hexdec(substr($color, 4, 2))
            );
        } else {
            $r = substr($color, 0, 1) . substr($color, 0, 1);
            $g = substr($color, 1, 1) . substr($color, 1, 1);
            $b = substr($color, 2, 1) . substr($color, 2, 1);
            $rgb = array(
                'r' => hexdec($r),
                'g' => hexdec($g),
                'b' => hexdec($b)
            );
        }
        return $rgb;
    }


    /**
     * 合成图片 - 用于生成群头像
     * @param array  $picList [图片列表数组]
     * @param boolean $isSave  [是否保存，true保存，false输出到浏览器]
     * @param string $savePath [保存路径]
     * @return boolean|string
     */
    public function getGroupAvatar($picList = [], $isSave = false, $savePath = ''){
        //验证参数
//        if(empty($picList) || empty($savePath)){
        if(empty($picList)){
            return false;
        }
        if($isSave){
            //如果需要保存，需要传保存地址
            if(empty($savePath)){
                return false;
            }
        }
        // 只操作前9个图片
        $picList = array_slice($picList, 0, 9);
        //设置背景图片宽高
        $bg_w = 150; // 背景图片宽度
        $bg_h = 150; // 背景图片高度
        //新建一个真彩色图像作为背景
        $background = imagecreatetruecolor($bg_w,$bg_h);
        //为真彩色画布创建白灰色背景，再设置为透明
        $color = imagecolorallocate($background, 202, 201, 201);
        imagefill($background, 0, 0, $color);
        imageColorTransparent($background, $color);

        // 图片背景处理
        // 描边
//        list($background, $handleLogoWidth, $handleLogoHeight) = $this->imageOutline($background);

        // 圆角处理
//        $background = $this->imageFillet($background);

        //根据图片个数设置图片位置
        $pic_count = count($picList);
        $lineArr = [];//需要换行的位置
        $space_x = 3;
        $space_y = 3;
        $line_x = 0;
        switch($pic_count) {
            case 1: // 正中间
                $start_x = intval($bg_w / 4); // 开始位置X
                $start_y = intval($bg_h / 4); // 开始位置Y
                $pic_w = intval($bg_w / 2); // 宽度
                $pic_h = intval($bg_h / 2); // 高度
                break;
            case 2: // 中间位置并排
                $start_x = 2;
                $start_y = intval($bg_h/4) + 3;
                $pic_w = intval($bg_w/2) - 5;
                $pic_h = intval($bg_h/2) - 5;
                $space_x = 5;
                break;
            case 3:
                $start_x = 40; // 开始位置X
                $start_y = 5; // 开始位置Y
                $pic_w = intval($bg_w/2) - 5; // 宽度
                $pic_h = intval($bg_h/2) - 5; // 高度
                $lineArr = array(2);
                $line_x = 4;
                break;
            case 4:
                $start_x = 4; // 开始位置X
                $start_y = 5; // 开始位置Y
                $pic_w = intval($bg_w/2) - 5; // 宽度
                $pic_h = intval($bg_h/2) - 5; // 高度
                $lineArr = array(3);
                $line_x = 4;
                break;
            case 5:
                $start_x = 30; // 开始位置X
                $start_y = 30; // 开始位置Y
                $pic_w = intval($bg_w/3) - 5; // 宽度
                $pic_h = intval($bg_h/3) - 5; // 高度
                $lineArr = array(3);
                $line_x = 5;
                break;
            case 6:
                $start_x = 5; // 开始位置X
                $start_y = 30; // 开始位置Y
                $pic_w = intval($bg_w/3) - 5; // 宽度
                $pic_h = intval($bg_h/3) - 5; // 高度
                $lineArr = array(4);
                $line_x = 5;
                break;
            case 7:
                $start_x = 53; // 开始位置X
                $start_y = 5; // 开始位置Y
                $pic_w = intval($bg_w/3) - 5; // 宽度
                $pic_h = intval($bg_h/3) - 5; // 高度
                $lineArr = array(2,5);
                $line_x = 5;
                break;
            case 8:
                $start_x = 30; // 开始位置X
                $start_y = 5; // 开始位置Y
                $pic_w = intval($bg_w/3) - 5; // 宽度
                $pic_h = intval($bg_h/3) - 5; // 高度
                $lineArr = array(3,6);
                $line_x = 5;
                break;
            case 9:
                $start_x = 5; // 开始位置X
                $start_y = 5; // 开始位置Y
                $pic_w = intval($bg_w/3) - 5; // 宽度
                $pic_h = intval($bg_h/3) - 5; // 高度
                $lineArr = array(4,7);
                $line_x = 5;
                break;
        }
        foreach( $picList as $k => $pic_path ) {
            $kk = $k + 1;
            if ( in_array($kk, $lineArr) ) {
                $start_x = $line_x;
                $start_y = $start_y + $pic_h + $space_y;
            }
            //获取图片文件扩展类型和mime类型，判断是否是正常图片文件
            //非正常图片文件，相应位置空着，跳过处理
            $image_mime_info = @getimagesize($pic_path);
            if($image_mime_info && !empty($image_mime_info['mime'])){
                $mime_arr = explode('/',$image_mime_info['mime']);
                if(is_array($mime_arr) && $mime_arr[0] == 'image' && !empty($mime_arr[1])){
                    switch($mime_arr[1]) {
                        case 'jpg':
                        case 'jpeg':
                            $imagecreatefromjpeg = 'imagecreatefromjpeg';
                            break;
                        case 'png':
                            $imagecreatefromjpeg = 'imagecreatefrompng';
                            break;
                        case 'gif':
                        default:
                            $imagecreatefromjpeg = 'imagecreatefromstring';
                            $pic_path = file_get_contents($pic_path);
                            break;
                    }
                    //创建一个新图像
                    $resource = $imagecreatefromjpeg($pic_path);

                    // 描边
                    list($resource, $handleLogoWidth, $handleLogoHeight) = $this->imageOutline($resource,5);

                    // 圆角处理
                    $resource = $this->imageFillet($resource);

                    //将图像中的一块矩形区域拷贝到另一个背景图像中
                    // $start_x,$start_y 放置在背景中的起始位置
                    // 0,0 裁剪的源头像的起点位置
                    // $pic_w,$pic_h copy后的高度和宽度
                    imagecopyresized($background,$resource,$start_x,$start_y,0,0,$pic_w,$pic_h,imagesx($resource),imagesy($resource));
                }
            }
            // 最后两个参数为原始图片宽度和高度，倒数两个参数为copy时的图片宽度和高度
            $start_x = $start_x + $pic_w + $space_x;
        }

        if($isSave){
            $dir = pathinfo($savePath,PATHINFO_DIRNAME);
            if(!is_dir($dir)){
                $file_create_res = mkdir($dir,0777,true);
                if(!$file_create_res){
                    return false;//没有创建成功
                }
            }
            $res = imagejpeg($background,$savePath);
            imagedestroy($background);
            if($res){
                return true;
            }else{
                return false;
            }
        }else{
            //直接输出
            ob_start();   //启用输出缓冲
            imagepng($background);    //输出图像
            $backgroundContent = ob_get_contents();    //将缓冲的数据存入变量
            ob_end_clean();    //结束并清空输出缓存
            return $backgroundContent;
//            header("Content-type: image/jpg");
//            imagejpeg($background);
//            imagedestroy($background);
        }
    }


}